package reflect;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;

/**
 * 自动调用与当前类ReflectDemo7所在同一个包中，自动调用本类自己定义的无参的公开方法
 */
public class ReflectDemo7 {
    /**
     * main方法上的参数String[] args的作用是
     * 在命令行上使用java命令指定当前类时，可以传递参数进来，此时会被main上的String[] args接收
     *
     * 例如:
     * java ReflectDemo7 arg1 arg2 arg3
     * main方法执行后，args数组就有三个元素，对应的就是"arg1","arg2","arg3"
     *
     */
    public static void main(String[] args) throws Exception {
        /*
            两个开发中常用的相对路径
         */
        //1这里的当前目录表示的是当前ReflectDemo7这个类所在最外层包的上一级目录
//        File dir = new File(
//                ReflectDemo7.class.getClassLoader().getResource(".").toURI()
//        );

        //2这里的当前目录就是当前类所在的目录
        File dir = new File(
                ReflectDemo7.class.getResource(".").toURI()
        );

        System.out.println(dir.getName());

        //通过当前类ReflectDemo7的类对象获取所在的包名
        String packageName = ReflectDemo7.class.getPackage().getName();
        System.out.println("ReflectDemo7类的包名是:"+packageName);

        //获取ReflectDemo7.class文件所在的目录中所有.class文件
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){
            //获取字节码文件的文件名
            String fileName = sub.getName();
            System.out.println(fileName);
            /*
                由于java命名要求，文件名必须与类名一致，所以我们可以通过文件名得知该字节码
                文件中保存的类的类名
             */
            String className = fileName.substring(0,fileName.indexOf("."));
//            System.out.println("类名:"+className);

            //加载该类的类对象
            Class cls = Class.forName(packageName+"."+className);
            Object obj = cls.newInstance();
//            System.out.println("加载的类为:"+cls.getName());
            //通过类对象获取本类定义的所有方法
            Method[] methods = cls.getDeclaredMethods();
            //遍历每个方法，检查哪个方法是无参的
            for(Method method : methods){
                if(
                        method.getParameterCount()==0
                        &&
                        method.getModifiers() == Modifier.PUBLIC
                ){
                    System.out.println("自动调用"+className+"的方法:"+method.getName());
                    method.invoke(obj);
                }
            }

        }


    }
}
